<?php
abstract class Db {
	protected $table = '';
	protected $querys = array();
	protected $state = array();
	protected $options = array();
	
	private final function __construct() {}
	
	public static function factory($driver, $single = true) {
		static $_instance = array();
		$className = "Db_{$driver}";
		if (class_exists($className)) {
			if ($single) {
				if (!isset($_instance[$driver])) {
					$_instance[$driver] = new $className();
				}
				return $_instance[$driver];
			}
			return new $className();
		}
		throw new Db_Exception("can not find db driver: $driver");
	}
	
	/**
	 * 设置数据库配置信息
	 *
	 * @param array $options
	 */
	public function setOptions($options) {
		$this->options = $options;
	}
	
	/**
	 * 设置当前操作表
	 *
	 * @param string $table
	 */
	public function setTable($table) {
		$this->table = $table;
	}
	
	/**
	 * 获取包含前缀的表名
	 * @see Db_Interface::getTable()
	 */
	public function getTable($table = '') {
		if (empty($table)) $table = $this->table;
		return $this->options['prefix'].$table;
	}
	
	/**
	 * 设置表前缀
	 *
	 * @param string $prefix
	 */
	public function setPrefix($prefix) {
		$this->options['prefix'] = $prefix;
	}
	
	/**
	 * (non-PHPdoc)
	 * @see Db_Interface::getPrefix()
	 */
	public function getPrefix() {
		return isset($this->options['prefix']) ? $this->options['prefix'] : '';
	}
	
	/**
	 * 读取一条记录
	 *
	 * @param int $id 主键
	 * @param string $table 表名
	 * @param unknown_type $idName
	 */
	public function get($id, $table, $idName = 'id') {
		$id = $this->escape($id);
		$sql = "SELECT * FROM {$table} WHERE {$idName} = '$id'";
		return $this->getRow($sql);
	}
	
	/**
	 * 获取第一条记录某个字段的值
	 * @see Db_Interface::getOne()
	 */
	public function getOne($sql, $index = 0) {
		$result = $this->getRow($sql);
		return (is_array($result) ? (isset($result[$index]) ? $result[$index] : array_shift($result)) : $result);
	}
	
	/**
	 * 添加一条记录
	 * @param array $data
	 * @param string $table
	 * @param boolean $replace
	 */
	public function add($data, $table = '', $replace = false) {
		if (empty($table)) $table = $this->getTable();
		$method = $replace ? 'REPLACE ' : 'INSERT';
		$fields = $values = $split = '';
		foreach ( $data as $key => $val ) {
			$fields .= $split."`$key`";
			$values .= $split."'$val'";
			$split = ', ';
		}
		$sql = "$method INTO `$table` ($fields) VALUES ($values)";
		$this->execute($sql);
		return $this->getInsertId();
	}
	
	/**
	 * 删除记录
	 * 
	 * @param string $id 主键值
	 * @param string $table 表名
	 * @param string $idName 主键字段名
	 */
	public function delete($where, $table = '') {
		if (empty($table)) $table = $this->getTable();
		$sql = "DELETE FROM `$table` WHERE 1";
		foreach ($where as $key => $val) {
			$sql .= " AND `".$this->escape($key)."`".(is_array($val)?" IN (".String::simplode($val).")":" = '".$this->escape($val)."'");
		}
		$this->execute($sql);
		return $this->affectedRows();
	}
	
	/**
	 * 更新记录
	 * 
	 * @param array $data 更新的数据
	 * @param string $id 主键值
	 * @param string $table 表名
	 * @param string $idName 主键字段名
	 */
	public function update($data, $where, $table = '') {
		if (empty($table)) $table = $this->getTable();
		$updatesql = $split = '';
		foreach ($data as $key => $val) {
			$updatesql .= $split."`$key` = '".$this->escape($val)."'";
			$split = ', ';
		}
		foreach ($where as $key => $val) {
			$wheresql .= " AND `{$key}`".(is_array($val)?" IN (".String::simplode($val).")":" = '".$this->escape($val)."'");
		}
		$sql = "UPDATE `$table` SET $updatesql WHERE 1 $wheresql";
		$this->execute($sql);
		return $this->getAffectedRows();
	}
	
	/**
	 * (non-PHPdoc)
	 * @see Db_Interface::count()
	 */
	public function count($table, $wheresql = '') {
		$sql = "SELECT COUNT(*) FROM {$table}";
		if ($wheresql) $sql .= " WHERE {$wheresql}";
		return intval($this->getOne($sql));
	}
	
	public function getAffectedRows() {
		return $this->state['affected_rows'] ? $this->state['affected_rows'] : false;
	}
	
	public function getInsertId() {
		return $this->state['last_insert_id'] ? $this->state['last_insert_id'] : false;
	}
}
